package com.star.config;

import com.star.filter.TokenAuthFilter;
import com.star.filter.TokenLoginFilter;
import com.star.security.DefaultPasswordEncoder;
import com.star.security.TokenLogoutHandler;
import com.star.security.TokenManager;
import com.star.security.UnauthEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class TokenWebSecurityConfig extends WebSecurityConfigurerAdapter {


    private TokenManager tokenManager;

    private StringRedisTemplate stringRedisTemplate;

    private DefaultPasswordEncoder defaultPasswordEncoder;

    private UserDetailsService userDetailsService;

    @Autowired
    public TokenWebSecurityConfig(UserDetailsService userDetailsService, DefaultPasswordEncoder defaultPasswordEncoder,
                                  TokenManager tokenManager, StringRedisTemplate stringRedisTemplate) {
        this.userDetailsService = userDetailsService;
        this.defaultPasswordEncoder = defaultPasswordEncoder;
        this.tokenManager = tokenManager;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    /**
     * 设置退出的地址和token，redis操作地址
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling()
                //没有权限访问
                .authenticationEntryPoint(new UnauthEntryPoint())
                .and().csrf().disable()
                .authorizeRequests()
//                .antMatchers("/admin/login",
//                        "/actuator/health",
//                        "/",
//                        "/**/swagger-resources/**",
//                        "/**/webjars/**",
//                        "/**/doc.html/**",
//                        "/**/v2/**",
//                        "/**/swagger-ui.html/**").permitAll()
                .anyRequest().authenticated()
                //退出路径
                .and().logout().logoutUrl("/admin/logout")
                .addLogoutHandler(new TokenLogoutHandler(tokenManager, stringRedisTemplate)).and()
                .addFilter(new TokenLoginFilter(authenticationManager(), tokenManager, stringRedisTemplate))
                .addFilter(new TokenAuthFilter(authenticationManager(), tokenManager, stringRedisTemplate)).httpBasic();
    }

    /**
     * 调用userDetailsService和密码处理
     *
     * @param auth
     * @throws Exception
     */
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(defaultPasswordEncoder);
    }

    /**
     * 不进行认证的路径，可以直接访问
     *
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers(
                "/actuator/health",
                "/",
                "/**/swagger-resources/**",
                "/**/webjars/**",
                "/**/doc.html/**",
                "/**/v2/**",
                "/**/swagger-ui.html/**",
                "/images/**");
    }
}
